\ProvidesExplPackage {env} {2023/01/01} {0.0.1} {MAL~environments}
\RequirePackage{types}

\prop_new:N \l_mal_repl_env_prop

% Scratch variable containing the name of an enviromnent as a token
% list, intended to be used with :c expansion.
\tl_new:N \l_mal_tmp_env_prop

% Note that __outer__ is not a valid key.

% The new environment is returned in \l_mal_tmp_env_prop.
\cs_new:Nn \mal_env_new:N
  {
    % \iow_term:n {env_new:~outer=#1}
    \int_incr:N \l_mal_object_counter_int
    \tl_set:Nx \l_mal_tmp_env_prop { env_ \int_use:N \l_mal_object_counter_int }
    \prop_new:c \l_mal_tmp_env_prop
    \prop_put:cnn \l_mal_tmp_env_prop { __outer__ } { #1 }
  }

% \prop_put:Nnn is OK for a single assignment.

% Shortcut for repeated '\prop_put:cnn \l_mal_tmp_env_prop' assignments,
% with special handling of & variable arguments.

\tl_const:Nx \c_ampersand_symbol { y \tl_to_str:n { & } }

\cs_new:Nn \mal_env_set_keys_values:nn
  {
    % \iow_term:n {apply_loop:~keys=#1~vals=#2}
    \tl_if_empty:nF { #1 }
      {
        \tl_set:Nx \l_tmpb_tl { \tl_head:n { #1 } }
        \tl_if_eq:NNTF \l_tmpb_tl \c_ampersand_symbol
           { \prop_put:cxn \l_mal_tmp_env_prop { \tl_item:nn { #1 } { 2 } }
               { l n #2 } }
          {
            \prop_put:cVx \l_mal_tmp_env_prop \l_tmpb_tl { \tl_head:n { #2 } }
            \mal_env_set_keys_values:oo { \use_none:n #1 } { \use_none:n #2 }
          }
      }
  }
\cs_generate_variant:Nn \mal_env_set_keys_values:nn { on, oo }

\cs_new:Nn \mal_env_get:NnTF
  {
    % \iow_term:n {env_get:~env=#1~key=#2}
    \prop_get:NnNTF #1 { #2 } \l_tmpa_tl
      { #3 }
      {
        \prop_get:NnNTF #1 { __outer__ } \l_tmpa_tl
          { \exp_args:NV \mal_env_get:NnTF \l_tmpa_tl { #2 } { #3 } { #4 } }
          { #4 }
      }
  }
% This one is useful for macroexpand, but may disappear once it is removed.
\cs_generate_variant:Nn \mal_env_get:NnTF { NxTF }
\cs_new:Nn \mal_env_get:NnT { \mal_env_get:NnTF #1 { #2 } { #3 } { } }
\cs_new:Nn \mal_env_get:NnF { \mal_env_get:NnTF #1 { #2 } { } { #3 } }
\cs_generate_variant:Nn \mal_env_get:NnT { NVT }
